#include "serialPortImp.h"
#include "helper.h"

int fd = -1;

jobject open(JNIEnv *env, jobject obj, jstring path, jint baud_rate, jint flags) {
    try {
        speed_t speed;
        /* Check arguments */
        {
            speed = getBaudRate(baud_rate);
            if (speed == -1) {
                LOG_E("getBaudRate 波特率不存在");
                return nullptr;
            }
        }
        /* Opening device */
        {
            jboolean iscopy;
            const char *path_utf = (*env).GetStringUTFChars(path, &iscopy);
            fd = open(path_utf, O_RDWR | flags);
            (*env).ReleaseStringUTFChars(path, path_utf);
            if (fd == -1) {
                LOG_E("串口路径打开失败");
                return nullptr;
            }
        }
        /* Configure device */
        {
            struct termios cfg{};
            if (tcgetattr(fd, &cfg)) {
                close(fd);
                return nullptr;
            }
            cfmakeraw(&cfg);
            cfsetispeed(&cfg, speed);
            cfsetospeed(&cfg, speed);
            if (tcsetattr(fd, TCSANOW, &cfg)) {
                close(fd);

                return nullptr;
            }
        }
        jobject fileDescriptor = getFileDescriptor(env, obj);
        return fileDescriptor;
    } catch (const std::exception &e) {
    }
    return nullptr;
}


jobject getFileDescriptor(JNIEnv *env, jobject obj) {
    if (fd == -1) {
        return nullptr;
    }
    try {
        jclass cFileDescriptor = (*env).FindClass("java/io/FileDescriptor");
        jmethodID iFileDescriptor = (*env).GetMethodID(cFileDescriptor, "<init>", "()V");
        jfieldID descriptorID = (*env).GetFieldID(cFileDescriptor, "descriptor", "I");
        jobject mFileDescriptor = (*env).NewObject(cFileDescriptor, iFileDescriptor);
        (*env).SetIntField(mFileDescriptor, descriptorID, (jint) fd);
        return mFileDescriptor;
    }catch (const std::exception &e){
    }
    return nullptr;
}

jint close(JNIEnv *env, jobject obj) {
    try {
        if (fd == -1) {
            return -1;
        }
        jint closeJint = close(fd);
        return closeJint;
    } catch (const std::exception &e) {

    }
    return -1;
}

